package com.example.socketchat.monitor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.text.NumberFormat;

/**
 * 性能监控组件
 * 
 * 用于在高并发压力测试时实时监控系统资源使用情况
 * 包括JVM内存使用、线程数量和系统负载等关键指标
 * 通过定时任务定期收集并输出监控数据
 */
@Slf4j  // Lombok日志注解
@Component  // Spring组件注解
@EnableScheduling  // 启用定时任务
@ConditionalOnProperty(name = "monitor.performance", havingValue = "true", matchIfMissing = false)  // 根据配置条件决定是否创建此Bean
public class PerformanceMonitor {

    // JVM内存监控Bean
    private final MemoryMXBean memoryMXBean;
    // 线程监控Bean
    private final ThreadMXBean threadMXBean;
    // 操作系统监控Bean
    private final OperatingSystemMXBean osMXBean;
    // 运行时环境
    private final Runtime runtime;
    // 数字格式化工具
    private final NumberFormat format = NumberFormat.getInstance();

    // 监控间隔时间，从配置文件读取
    @Value("${monitor.interval:10000}")
    private long monitorInterval;

    /**
     * 构造函数，初始化各种监控组件
     */
    public PerformanceMonitor() {
        // 获取JVM内存监控MXBean
        this.memoryMXBean = ManagementFactory.getMemoryMXBean();
        // 获取线程监控MXBean
        this.threadMXBean = ManagementFactory.getThreadMXBean();
        // 获取操作系统监控MXBean
        this.osMXBean = ManagementFactory.getOperatingSystemMXBean();
        // 获取运行时环境
        this.runtime = Runtime.getRuntime();
        
        // 设置数字格式化精度
        format.setMaximumFractionDigits(2);
        log.info("性能监控已启动，监控间隔：{}毫秒", monitorInterval);
    }

    /**
     * 定时收集并记录性能指标
     * 此方法会按照配置的时间间隔定期执行
     */
    @Scheduled(fixedDelayString = "${monitor.interval:10000}")
    public void monitorSystemPerformance() {
        // 收集内存使用信息
        long heapUsed = memoryMXBean.getHeapMemoryUsage().getUsed();  // 已使用的堆内存
        long heapMax = memoryMXBean.getHeapMemoryUsage().getMax();    // 最大可用堆内存
        double heapUsage = (double) heapUsed / heapMax * 100;         // 内存使用率
        
        // 收集线程信息
        int threadCount = threadMXBean.getThreadCount();          // 当前线程数
        int peakThreadCount = threadMXBean.getPeakThreadCount();  // 峰值线程数
        
        // 收集系统负载信息
        double systemLoad = osMXBean.getSystemLoadAverage();    // 系统平均负载
        int availableProcessors = runtime.availableProcessors();  // 可用处理器核心数
        
        // 输出格式化的性能监控数据
        log.info("===== 性能监控 =====");
        log.info("JVM堆内存: {}MB / {}MB ({}%)", 
                format.format(heapUsed / (1024.0 * 1024.0)),
                format.format(heapMax / (1024.0 * 1024.0)),
                format.format(heapUsage));
        log.info("线程数: {} (峰值: {})", threadCount, peakThreadCount);
        log.info("系统负载: {} (CPU核心数: {})", 
                systemLoad >= 0 ? format.format(systemLoad) : "不可用", 
                availableProcessors);
        log.info("=====================");
    }
} 